package com.ly.push.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ly.push.param.MyTimeProperties;
import com.ly.push.param.weather.WeatherInfo;
import com.ly.push.param.WxMpProperties;
import com.ly.push.param.wx.WxMsgBean;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * 加密,字典排序
 */
@Slf4j
@Component
public class WxUtils {

    @Resource
    private WxMpProperties wxMpProperties;
    @Resource
    private MyTimeProperties myTimeProperties;
    @Resource
    private RainUtils rainUtils;
    @Resource
    WeatherUtils weatherUtils;

    //发送消息
    public void pushTemplate(String openId){
        //1，配置
        WxMpInMemoryConfigStorage wxStorage = new WxMpInMemoryConfigStorage();
        wxStorage.setAppId(wxMpProperties.getAppId());
        wxStorage.setSecret(wxMpProperties.getSecret());
        WxMpService wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(wxStorage);
        //2,推送消息
        WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
                .toUser(openId)//推送用户
                .templateId(wxMpProperties.getPushTemplateId())//模板id
                .build();
        String text = "❤";
        templateMessage.addData(new WxMpTemplateData("text",text,"#FF0000"));
        String rain = rainUtils.getRain();
        templateMessage.addData(new WxMpTemplateData("rain",rain,"#FF1493"));
        try {
            wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
        } catch (Exception e) {
            log.error("推送失败：" + e.getMessage());
            e.printStackTrace();
        }
    }

    /*模板，直接选中下面的赋值就可

{{data.DATA}}

地区：{{cityName.DATA}}

天气：{{type.DATA}}

气温：{{hl.DATA}}

风向：{{fengxiang.DATA}}

风力：{{fengli.DATA}}

今天是我们{{loveDayText.DATA}}的第{{loveDay.DATA}}天

距离{{birthday2Text.DATA}}的生日还有{{birthday2.DATA}}天

距离{{birthday1Text.DATA}}的生日还有{{birthday1.DATA}}天

距离{{loveDay1Text.DATA}}还有{{loveDay1.DATA}}天

{{rain.DATA}}
     */
    public void pushTemplate1(String openId){
        //1，配置
        WxMpInMemoryConfigStorage wxStorage = new WxMpInMemoryConfigStorage();
        wxStorage.setAppId(wxMpProperties.getAppId());
        wxStorage.setSecret(wxMpProperties.getSecret());
        WxMpService wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(wxStorage);
        //2,推送消息
        WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
                .toUser(openId)//推送用户
                .templateId(wxMpProperties.getPushTemplateId1())//模板id
                .build();
        String text = "❤";
        templateMessage.addData(new WxMpTemplateData("text",text,"#FF0000"));
        String rain = rainUtils.getRain();
        templateMessage.addData(new WxMpTemplateData("rain",rain,"#C71585"));
        WeatherInfo weatherInfo = weatherUtils.getWeather("临沂");
        if (weatherInfo != null){
            String date = weatherInfo.getDate();
            templateMessage.addData(new WxMpTemplateData("data",date,"#FF1493"));
            templateMessage.addData(new WxMpTemplateData("cityName","山东❤临沂","#FF0000"));
            templateMessage.addData(new WxMpTemplateData("type",weatherInfo.getType(),"#FF1493"));
            String hl = weatherInfo.getLow() +"~" +weatherInfo.getHigh();
            templateMessage.addData(new WxMpTemplateData("hl",hl,"#EA7F7F"));
            templateMessage.addData(new WxMpTemplateData("fengxiang",weatherInfo.getFengxiang(),"#FFA500"));
            String fengli = weatherInfo.getFengli();
            templateMessage.addData(new WxMpTemplateData("fengli",fengli,"#FFA500"));
        }
//        WeatherInfo weatherInfo = WeatherUtils.getWeather("临沂");
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//        Date d = new Date();
//        if (weatherInfo != null){
//            String date = weatherInfo.getDate();
//            String data1 = date.substring(date.indexOf("星"));
//            String d1 = sdf.format(d)+" "+data1;
//            templateMessage.addData(new WxMpTemplateData("data",d1,"#FF1493"));
//            templateMessage.addData(new WxMpTemplateData("cityName","山东❤临沂","#FF0000"));
//            templateMessage.addData(new WxMpTemplateData("type",weatherInfo.getType(),"#FF1493"));
//            String hl = weatherInfo.getLow() +"~" +weatherInfo.getHigh();
//            templateMessage.addData(new WxMpTemplateData("hl",hl,"#EA7F7F"));
//            templateMessage.addData(new WxMpTemplateData("fengxiang",weatherInfo.getFengxiang(),"#FFA500"));
//            String fengli = weatherInfo.getFengli();
//            templateMessage.addData(new WxMpTemplateData("fengli",fengli.substring(fengli.indexOf("A[")+2,fengli.indexOf("]]")),"#FFA500"));
//        }
        String birthday1 = myTimeProperties.getBirthday1();
        String birthday2 = myTimeProperties.getBirthday2();
        String day1 = myTimeProperties.getDay1();
        // calcBirthday 方法是计算还距离日期还有多少天
        // calcDay 是计算已经过去多少天
        templateMessage.addData(new WxMpTemplateData("birthday1",String.valueOf(TimeUtils.calcBirthday(birthday1)),"#FF1493"));
        templateMessage.addData(new WxMpTemplateData("birthday2",String.valueOf(TimeUtils.calcBirthday(birthday2)),"#FF1493"));
        templateMessage.addData(new WxMpTemplateData("loveDay1",String.valueOf(TimeUtils.calcBirthday(day1)),"#FF1493"));
        templateMessage.addData(new WxMpTemplateData("loveDay",String.valueOf(TimeUtils.calcDay(day1)),"#FF1493"));

        templateMessage.addData(new WxMpTemplateData("loveDayText","恋爱","#FF1493"));
        templateMessage.addData(new WxMpTemplateData("loveDay1Text","周年纪念日","#FF1493"));
        templateMessage.addData(new WxMpTemplateData("birthday1Text",myTimeProperties.getName1(),"#FF1493"));
        templateMessage.addData(new WxMpTemplateData("birthday2Text",myTimeProperties.getName2(),"#FF1493"));
        try {
            wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
        } catch (Exception e) {
            log.error("推送失败：" + e.getMessage());
            e.printStackTrace();
        }
    }

    //发送天气
    /*
地址：{{cityName.DATA}}

时间：{{weatherDate.DATA}}

天气：{{weatherType.DATA}}
     */
    public void pushWeather(String openId,String province,String city){
        //1，配置
        WxMpInMemoryConfigStorage wxStorage = new WxMpInMemoryConfigStorage();
        wxStorage.setAppId(wxMpProperties.getAppId());
        wxStorage.setSecret(wxMpProperties.getSecret());
        WxMpService wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(wxStorage);
        //2,推送消息
        WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
                .toUser(openId)//推送用户
                .templateId(wxMpProperties.getWeatherTemplateId())//模板id
                .build();
        WeatherInfo weatherInfo = weatherUtils.getWeather(city);
        templateMessage.addData(new WxMpTemplateData("cityName",province+city,"#C71585"));
        templateMessage.addData(new WxMpTemplateData("weatherDate",weatherInfo.getDate(),"#C71585"));
        templateMessage.addData(new WxMpTemplateData("weatherType",weatherInfo.getType(),"#C71585"));
        //配置个人信息
        //粉色  FF1493
        //橙色  FFA500
        //红色  FF0000
        try {
            wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
        } catch (Exception e) {
            log.error("推送失败："+ e.getMessage());
            e.printStackTrace();
        }
    }

    //发送生日纪念日什么的
    /*
生日:{{birthday1.DATA}}{{goto.DATA}}还剩:{{birthday11.DATA}}天

生日:{{birthday2.DATA}}{{goto.DATA}}还剩:{{birthday22.DATA}}天

在一起的纪念日:{{day1.DATA}}{{goto.DATA}}还剩:{{day11.DATA}}天

{{text.DATA}}
    */
    public void pushDate(String openId){
        //1，配置
        WxMpInMemoryConfigStorage wxStorage = new WxMpInMemoryConfigStorage();
        wxStorage.setAppId(wxMpProperties.getAppId());
        wxStorage.setSecret(wxMpProperties.getSecret());
        WxMpService wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(wxStorage);
        //2,推送消息
        WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
                .toUser(openId)//推送用户
                .templateId(wxMpProperties.getBirthdayTemplateId())//模板id
                .build();
        String birthday1 = myTimeProperties.getBirthday1();
        String birthday2 = myTimeProperties.getBirthday2();
        String day1 = myTimeProperties.getDay1();
        templateMessage.addData(new WxMpTemplateData("birthday1",birthday1,"#C71585"));
        templateMessage.addData(new WxMpTemplateData("birthday2",birthday2,"#C71585"));
        templateMessage.addData(new WxMpTemplateData("day1",day1,"#C71585"));
        templateMessage.addData(new WxMpTemplateData("birthday11",String.valueOf(TimeUtils.calcBirthday(birthday1)),"#FF1493"));
        templateMessage.addData(new WxMpTemplateData("birthday22",String.valueOf(TimeUtils.calcBirthday(birthday2)),"#FF1493"));
        templateMessage.addData(new WxMpTemplateData("day11",String.valueOf(TimeUtils.calcBirthday(day1)),"#FF1493"));
        //配置个人信息
        //粉色  FF1493
        //橙色  FFA500
        //红色  FF0000
        String text = "❤";
        templateMessage.addData(new WxMpTemplateData("text",text,"#FF0000"));
        templateMessage.addData(new WxMpTemplateData("goto","===>","#FFA500"));
        try {
            wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
        } catch (Exception e) {
            log.error("推送失败："+ e.getMessage());
            e.printStackTrace();
        }
    }

    //加密
    public String SHA1(String decript) {
        try {
            MessageDigest digest = MessageDigest
                    .getInstance("SHA-1");
            digest.update(decript.getBytes());
            byte [] msg = digest.digest();
            // Create Hex String
            StringBuilder sb = new StringBuilder();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < msg.length; i++) {
                String shaHex = Integer.toHexString(msg[i] & 0xFF);
                if (shaHex.length() < 2) {
                    sb.append(0);
                }
                sb.append(shaHex);
            }
            return sb.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }

    //排序
    public String sort(String token, String timestamp, String nonce) {
        String[] strArray = { token, timestamp, nonce };
        Arrays.sort(strArray);

        StringBuilder sb = new StringBuilder();
        for (String str : strArray) {
            sb.append(str);
        }

        return sb.toString();
    }

    //文本转换为xml
    public static String wxMsgBeanToXml(WxMsgBean wxMsgBean) {
        XStream xStream = new XStream(new DomDriver("UTF-8"));
        //XStream xStream = new XStream();
        xStream.alias("xml", wxMsgBean.getClass());
        return xStream.toXML(wxMsgBean);
    }

    //回复消息
    public static String reply(String appID,String openId,String content) {
        WxMsgBean result = new WxMsgBean();
        result.setFromUserName(appID);
        result.setToUserName(openId);
        result.setCreateTime(new Date().getTime());
        result.setContent(content);
        result.setMsgType("text");
        //用这个工具类处理出一串玩意直接返回
        String xml = WxUtils.wxMsgBeanToXml(result);
        return xml;
    }

    //获取Access token
    //https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
    public static Map<String,String> getToken(String appId,String secret){
        StringBuilder data = new StringBuilder();
        BufferedReader in = null;
        try {
            URL realUrl = new URL("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appId+"&secret="+secret);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                data.append(line);
            }
        } catch (Exception e) {
            log.error("获取token异常");
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        JSONObject jsonObject = JSONObject.parseObject(data.toString());
        String accessToken = jsonObject.getString("access_token");
        Integer expiresIn = jsonObject.getInteger("expires_in");
        Map<String,String> map = new HashMap<>();
        map.put("accessToken",accessToken);
        map.put("expiresIn",expiresIn.toString());
        String nowTime = TimeUtils.dateToString(new Date());
        map.put("nowTime",nowTime);
        Integer i = expiresIn / 60 /60;
        String finalTime = TimeUtils.increaseTime(new Date(),i);
        map.put("finalTime",finalTime);
        return map;
    }

    //获取用户列表，一次拉取调用最多拉取10000个关注者的OpenID，可以通过多次拉取的方式来满足需求
    //https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID
    public static Map<String,Object> getUserList(String token){
        //存储所有的openIds
        List<String> openIds = new ArrayList<>();
        StringBuilder data = new StringBuilder();
        BufferedReader in = null;
        try {
            URL realUrl = new URL("https://api.weixin.qq.com/cgi-bin/user/get?access_token="+token);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                data.append(line);
            }
        } catch (Exception e) {
            log.error("获取用户列表异常");
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        //获得到的数据
        JSONObject jsonObject = JSONObject.parseObject(data.toString());
        JSONObject jsonObject1 = jsonObject.getJSONObject("data");
        JSONArray array = jsonObject1.getJSONArray("openid");
        for (int a = 0; a < array.size(); a++) {
            openIds.add(array.getString(a));
        }

        //总数
        Integer total = jsonObject.getInteger("total");;
        //当前拉取的条数
        Integer count = jsonObject.getInteger("count");
        //最后一个用户
        String nextOpenid =  jsonObject.getString("next_openid");
        BigDecimal decimal;
        //总页数
        int page = 0;
        //计算页数
        if (total>count){
            BigDecimal a = new BigDecimal(total);
            decimal = a.divide(BigDecimal.valueOf(10000));
            //两个数相比较，如果为小数，再少也自己占一次调用，占一页
            if (decimal.compareTo(new BigDecimal(decimal.intValue())) != 0){
                page = decimal.intValue() + 1;
            }
        }
        //已经调用完第一次所以去掉
        for (int i = 0; i < page-1; i++) {
            //清空 StringBuilder
            data.setLength(0);
            try {
                URL realUrl = new URL("https://api.weixin.qq.com/cgi-bin/user/get?access_token="+token+"&next_openid="+nextOpenid);
                // 打开和URL之间的连接
                URLConnection connection = realUrl.openConnection();
                // 设置通用的请求属性
                connection.setRequestProperty("accept", "*/*");
                connection.setRequestProperty("connection", "Keep-Alive");
                connection.setRequestProperty("user-agent",
                        "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                // 建立实际的连接
                connection.connect();
                // 获取所有响应头字段
                Map<String, List<String>> map = connection.getHeaderFields();
                // 定义 BufferedReader输入流来读取URL的响应
                in = new BufferedReader(new InputStreamReader(
                        connection.getInputStream()));
                String line;
                while ((line = in.readLine()) != null) {
                    data.append(line);
                }
            } catch (Exception e) {
                log.error("获取用户列表异常");
                e.printStackTrace();
            } finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
            //获得到的数据
            JSONObject jsonObject2 = JSONObject.parseObject(data.toString());
            JSONObject jsonObject3 = jsonObject2.getJSONObject("data");
            JSONArray array1 = jsonObject3.getJSONArray("openid");
            for (int a = 0; a < array1.size(); a++) {
                openIds.add(array1.getString(a));
            }
            nextOpenid =  jsonObject2.getString("next_openid");
        }
        Map<String,Object> map = new HashMap<>();
        map.put("total",total);
        map.put("openIds",openIds);
        return map;

    }

}

